<?php
namespace WDB\WebUI;
use WDB;

/**
  * Base iColumn implementation.
  * 
  * @author Richard Ejem <richard(at)ejem.cz>
  * @package WDB
  */
abstract class Column extends WDB\BaseObject implements iColumn, iOrderable, iFilterable
{
    /**@var \WDB\Wrapper\Column */
    protected $columnWrapper;
    /**@var iTable */
    protected $table;
    /**@var int flags determining on which views to display this column*/
    protected $display;
    
    /**
     *
     * @param WDB\Wrapper\iColumn column wrapper
     * @param iTable table webui
     */
    public function __construct(WDB\Wrapper\iColumn $columnWrapper, iTable $tableWebUI)
    {
        $this->columnWrapper = $columnWrapper;
        $this->table = $tableWebUI;
        
        if ($columnWrapper->isAutoColumn())
        {
            $this->setDisplayModes(iColumn::DISPLAY_AUTOCOLUMN_DEFAULT);
        }
        else
        {
            $this->setDisplayModes($this->getDefaultDisplayModes());
        }
        $this->setDisplayModes($columnWrapper->getWebUIDisplayMode($this->getDisplayModes()));
    }
    
    protected function getDefaultDisplayModes()
    {
        return ~0;
    }
    
    public function getName()
    {
        return $this->columnWrapper->name;
    }
    
    public function getTitle()
    {
        return $this->columnWrapper->title;
    }
    
    public function getTitleHTML()
    {
        return htmlspecialchars($this->columnWrapper->title);
    }
    
    public function getTable()
    {
        return $this->table;
    }
    
    public function addDisplayMode($mode)
    {
        $this->display |= $mode;
    }
    
    public function removeDisplayMode($mode)
    {
        $this->display &= ~$mode;
    }
    
    public function getDisplayModes()
    {
        return $this->display;
    }
    
    public function setDisplayModes($mode)
    {
        $this->display = (int)$mode;
    }
    
    public function isDisplayedList()
    {
        return $this->isDisplayed(iColumn::DISPLAY_LIST);
    }
    
    public function isDisplayedEdit()
    {
        return $this->isDisplayed(iColumn::DISPLAY_EDIT);
    }
    
    public function isDisplayedEditRead()
    {
        return $this->isDisplayed(iColumn::DISPLAY_EDIT_READONLY);
    }
    
    public function isDisplayedDetail()
    {
        return $this->isDisplayed(iColumn::DISPLAY_DETAIL);
    }
    
    public function isDisplayed($mode)
    {
        return ($this->display & $mode) == $mode;
    }
    
    public function isNullable()
    {
        return $this->columnWrapper->isNullable();
    }
    
    public function isDefaultInitializable()
    {
        return ($this->columnWrapper->isAutoColumn() || $this->columnWrapper->getDefault() !== NULL || $this->columnWrapper->isNullable());
    }
    
    public function getRules()
    {
        return $this->columnWrapper->rules;
    }
    
    public function parseInputValue(WDB\Wrapper\iRecord $record, $value)
    {
        if ($this->isNullable())
        {
            
            if (!empty($value['notnull']))
            {
                $v = $this->fetchInputValue(isset($value['value']) ? $value['value'] : '');
            }
            else
            {
                $v = NULL;
            }
        }
        else
        {
            $v = $this->fetchInputValue(isset($value['value']) ? $value['value'] : '');
        }
        $record->setFieldValue($this->getName(), $v);
    }
    
    /**
     * can be called by descendants' parseInputValue() when they have different or no way to express NULL
     * 
     * @param WDB\Wrapper\iRecord $record
     */
    protected function parseInputValueNoNullable(WDB\Wrapper\iRecord $record, $value)
    {
        $record->setFieldValue($this->getName(), $this->fetchInputValue(isset($value['value']) ? $value['value'] : ''));
    }
    
    /**
     * Translates string value read from request to a valid value of record wrapper's field.
     *
     * @param string value
     * @return mixed
     */
    protected function fetchInputValue($v)
    {
        return $v;
    }
    
    public function getSimpleHTML(WDB\Wrapper\iRecord $record)
    {
        return $this->getDetailedHTML($record);
    }
    
    public function getEditingHTML_nullator(WDB\Wrapper\iRecord $record)
    {
        if (!$this->isNullable()) return '';
        $input_name = $this->table->getRequest()->getSaveFieldName($this->name);
        $value = $record[$this->name];
        return '<input
            type="checkbox"
            name="'.htmlspecialchars($input_name).'[notnull]"
            value="1" '
            .($record[$this->name] !== NULL ? 'checked="checked"' : '').
            ' onclick="
                var inp = $(\'input[name=&quot;'.str_replace(array('[', ']'), array('\\[', '\\]'), htmlspecialchars($input_name)).'\[value\]&quot;]\');
                if (this.checked) inp.show();else inp.hide();
            "/>';        
    }
    
    protected function getInputHTMLNode(WDB\Wrapper\iRecord $record)
    {
        $input_name = $this->table->getRequest()->getSaveFieldName($this->name);
        $input = new HTMLNode('input');
        $input['type'] = 'text';
        $val = $record[$this->name];
        $input['name'] = $input_name.'[value]';
        if ($this->isNullable())
        {
            if ($val === NULL)
            {
                $input['data-wdbCommand'] = 'hide';
            }
        }
        $input['value'] = $val;
        return $input;
    }
    
    public function getEditingHTML(WDB\Wrapper\iRecord $record)
    {
        return $this->getInputHTMLNode($record)->__toString();   
    }
    
    public function getHTMLEditStatus(WDB\Wrapper\iRecord $record)
    {
        return implode('<br>', $record->getField($this->name)->getValidationErrors());
    }
    
    public function getDetailedHTML(WDB\Wrapper\iRecord $record)
    {
        return htmlspecialchars($record[$this->name]);
    }
    
    public function getSurroundingCSSClasses(WDB\Wrapper\iRecord $record)
    {
        if (count($record->getField($this->name)->getValidationErrors()) > 0)
        {
            return array('invalid');
        }
        return array();
    }
    
    public function isOrderable()
    {
        return $this->columnWrapper instanceof WDB\Wrapper\iOrderable && $this->columnWrapper->isOrderable();
    }
    
    public function isFilterable()
    {
        return $this->columnWrapper instanceof WDB\Wrapper\iFilterable && $this->columnWrapper->isFilterable();
    }
    
    public function isToggledOrder($asc = TRUE)
    {
        return $this->table->getRequest()->getOrderColumn() == $this->name
                && $this->table->getRequest()->isOrderAsc() == $asc;
    }
    
    public function isToggledFilter()
    {
        $f = $this->table->getRequest()->getFilters();
        return isset($f[$this->name]);
    }
    
    public function getFilterOptions()
    {
        return $this->columnWrapper->getFilterOptions();
    }
    
    public function getFilteredValue()
    {
        $f = $this->table->getRequest()->getFilters();
        if (isset($this->filterOptions[$f[$this->name]]))
        {
            return $this->getFilterStringValue($this->filterOptions[$f[$this->name]]);
        }
        else
        {
            return NULL;
        }
    }
    
    public function getFilterStringValue($val)
    {
        return (string)$val;
    }
}